package server;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;

import commons.Message;
import commons.OMGProtocol;
import commons.World;

/**
 * 
 * A single thread for each connection to a client
 * this class gets messages, sends messages, by
 * envoking the DFA
 *
 */
class OMGPConnectionThread extends Thread {


	private Socket serverSock;
	private int clientID;
	private HashMap<Integer, World> games;

	OMGPConnectionThread(Socket serverSock, int clientID, HashMap<Integer, World> games) {
		this.games = games;
		this.serverSock = serverSock;
		this.clientID = clientID;
	}

	public void run() {

		try {

			DataOutputStream out = new DataOutputStream(new BufferedOutputStream(this.serverSock.getOutputStream()));
			DataInputStream in = new DataInputStream(new BufferedInputStream(
					this.serverSock.getInputStream()));


			OMGProtocolForServer oProtocol = 
				new OMGProtocolForServer(OMGPServer.SERVER_NAME, games, clientID);

			// Send authentication request
			Message messageToSend = null;
			Message currentClientMessage = new Message();
			int pastState = -1;
			do {		
				if(oProtocol.getState() != pastState) {
					System.err.println("["+ clientID + "] Server is in state: " + oProtocol.getStateDescription());
					pastState = oProtocol.getState();
				}

				// Get the latest message
				if(in.available()>0 && currentClientMessage.isRead()) {
					try {
						currentClientMessage = new Message(in);
						System.err.println("[" + clientID + "] Message received: " + currentClientMessage.getMessageDescription());
					} catch (Exception e) {
						System.err.println("Malformed message, being fuzzed?");
					}
				}

				// Run the DFA
				try {
					messageToSend = oProtocol.runDFA(currentClientMessage);
				} catch (ClassNotFoundException e) {
					System.err.println("Error with game data ->"+e.getMessage());
				}


				// Check if there's a message to send
				if(messageToSend != null) { 
					try{
						messageToSend.send(out);
					} catch(Exception e) {
						System.err.println("Error sending message!");
					}
				}			

			}while (oProtocol.getState() != OMGProtocol.NONE);
			System.err.println("[Thread closed]");


			out.close();
			in.close();
			this.serverSock.close();

		} 
		catch (SocketException e) {
			System.err.println(" Socket Exception ->"+e.getMessage());
		} catch (IOException e) {
			System.err.println(" IOException ->"+e.getMessage());
			e.printStackTrace();
		}
	}

	public void close()
	{
		try {
			this.serverSock.close();
		} catch (IOException e) {

			e.printStackTrace();
		}
	}


}